﻿using System;
using System.Collections;
using System.Data;
using System.Web.UI.WebControls;

namespace Lime49.UI {
    public delegate IEnumerable MustAddARowHandler(IEnumerable data);

    /// <summary>
    /// Keeps the header row visible when there are no rows in the data source (so it can be unfiltered)
    /// Thanks Joe Wrobel - http://weblogs.asp.net/joewrobel/archive/2008/01/30/a-more-elegant-solution-to-display-gridview-header-and-footer-when-the-data-source-is-empty.aspx
    /// </summary>
    public class BetterGridView : GridView {
        public event MustAddARowHandler MustAddARow;
        public bool IsEmpty { get { return isEmpty; } }

        private bool isEmpty = false;

        protected override void OnDataBound(EventArgs e) {
            if(DesignMode) { //if in DesignMode, don't do anything special. Just call base and return.
                base.OnDataBound(e);
                return;
            }
            if(isEmpty) {
                Rows[0].Visible = false; //hide the dummy row.
            }
            base.OnDataBound(e);
        }

        protected override void PerformDataBinding(IEnumerable data) {
            //If in DesignMode, don't do anything special. Just call base and return.
            if(DesignMode) {
                base.PerformDataBinding(data);
                return;
            }

            //Count the data items.(I wish I knew a better way to do this.)
            int objectItemCount = 0;
            foreach(object o in data) {
                objectItemCount++;
            }

            //If there is a count, don't do anything special. Just call base and return.
            if(objectItemCount > 0) {
                base.PerformDataBinding(data);
                return;
            }

            //Set these values so the GridView knows what's up.
            SelectArguments.TotalRowCount++;
            isEmpty = true;

            //If it's a DataView, it will work without having to handle the MustAddARow event.
            if(data.GetType() == typeof(DataView)) {
                //Add a row and use that new view.
                DataView dv = (DataView)data;
                //dv.Table.Rows.InsertAt(dv.Table.NewRow(), 0);
                //Create a table with the same schema as data, but with no constraints
                DataTable dt = new DataTable(dv.Table.TableName);
                //copy columns
                foreach(DataColumn dc in dv.Table.Columns) {
                    dt.Columns.Add(dc.ColumnName);
                }
                //Add a row and use that new view.
                dt.Rows.Add(dt.NewRow());
                dv = new DataView(dt);

                base.PerformDataBinding(dv.Table.DefaultView);
                return;
            } else {
                //If you are using some custom object, you need to handle this event.
                base.PerformDataBinding(OnMustAddARow(data));
                return;
            }
        }

        protected IEnumerable OnMustAddARow(IEnumerable data) {
            if(MustAddARow == null) {
                throw new NullReferenceException("The datasource has no rows. You must handle the \"MustAddARow\" Event.");
            }
            return MustAddARow(data);
        }
        
    }
}